Add ADR for GitHub Actions support - #98
Conversation
| | Input | Required | Default | Description | | ||
| |-------|----------|---------|-------------| | ||
| | `prompt` | Yes | — | Task/prompt to pass to Claude Code | | ||
| | `anthropic-api-key` | Yes | — | Anthropic API key | |
There was a problem hiding this comment.
rather than an api key, let's use an oauth token
| | `prompt` | Yes | — | Task/prompt to pass to Claude Code | | ||
| | `anthropic-api-key` | Yes | — | Anthropic API key | | ||
| | `github-token` | Yes | — | GitHub token for git operations | | ||
| | `mode` | No | `public` | Network mode: `public` or `private` | |
There was a problem hiding this comment.
let's default to private for private repos
| | `github-token` | Yes | — | GitHub token for git operations | | ||
| | `mode` | No | `public` | Network mode: `public` or `private` | | ||
| | `timeout` | No | `30` | Timeout in minutes | | ||
| | `model` | No | `sonnet` | Claude model to use | |
|
|
||
| ## Open Questions | ||
|
|
||
| 1. **Issue/PR-triggered prompts:** Should the action support commenting `/egg fix this` on an issue to trigger a run with issue context as the prompt? This would require a separate workflow template. |
| ## Open Questions | ||
|
|
||
| 1. **Issue/PR-triggered prompts:** Should the action support commenting `/egg fix this` on an issue to trigger a run with issue context as the prompt? This would require a separate workflow template. | ||
| 2. **Image registry:** GHCR (free for public repos, integrated with GitHub) vs Docker Hub? |
| 1. **Issue/PR-triggered prompts:** Should the action support commenting `/egg fix this` on an issue to trigger a run with issue context as the prompt? This would require a separate workflow template. | ||
| 2. **Image registry:** GHCR (free for public repos, integrated with GitHub) vs Docker Hub? | ||
| 3. **Branch strategy in GHA:** Should the action always create new branches from the checked-out ref, or should it support pushing to the current branch? | ||
| 4. **Rate limiting:** Should the action enforce any rate limits on Claude API usage to prevent runaway costs? |
|
|
||
| 1. **Issue/PR-triggered prompts:** Should the action support commenting `/egg fix this` on an issue to trigger a run with issue context as the prompt? This would require a separate workflow template. | ||
| 2. **Image registry:** GHCR (free for public repos, integrated with GitHub) vs Docker Hub? | ||
| 3. **Branch strategy in GHA:** Should the action always create new branches from the checked-out ref, or should it support pushing to the current branch? |
There was a problem hiding this comment.
it should support both. We're building a fully autonomous agent here, let's keep the lockdowns as they are.
| timeout: 30 | ||
| ``` | ||
|
|
||
| ### Action Inputs |
There was a problem hiding this comment.
let's make the bot account configurable and support passing in the bot credentials as well. This should support the same setup as egg on a dev machine.
|
Worth noting, we're going to support this being triggered as an "ai linter" as well per #77. That'll be handled after this is implemented. |
There was a problem hiding this comment.
ADR Review: GitHub Actions Support
Solid design proposal that correctly preserves egg's security model. The phased approach is sensible. Several technical concerns to address before accepting.
Issues
1. Entrypoint flow describes a non-existent API sequence (Steps 6-7)
The ADR describes separate steps: "Create session + worktrees" (step 6) then "Start sandbox" (step 7). The actual gateway API uses POST /api/v1/session/create which atomically creates the session, allocates worktrees, and binds to a container IP. The launcher in sandbox/egg_lib/runtime.py calls _allocate_container_ip() first, then create_session() which does worktree creation internally. The ADR should reflect this actual flow or explain how it will differ for GHA.
2. Generated repositories.yaml is incomplete
The proposed config only has local_repos.paths and github_username, but the actual config format (per config/repositories.yaml.example) requires writable_repos, bot_username, user_mode block (with github_user, git_name, git_email), and repo_settings with auth_mode. The gateway's repo_parser.py will likely fail or behave unexpectedly with this minimal config. The ADR should specify the full generated config or explain what gateway changes are needed to accept a minimal config.
3. Anthropic API key routing is unclear
The sandbox sets ANTHROPIC_BASE_URL=http://egg-gateway:9848 and the gateway proxies API calls, injecting credentials. The ADR lists anthropic-api-key as an action input passed to the sandbox, but the current architecture has the gateway handle API key injection. The ADR should clarify whether the key goes to the gateway (matching current arch) or directly to the sandbox (diverging from it).
4. Build-from-source Phase 1 may be impractical
Building two Docker images from source on every GHA run is likely to take 5-15 minutes, especially the sandbox image which installs Python packages, Node.js, Claude Code, and numerous dev tools. Consider whether Phase 1 should use GHCR images from the start, or at minimum acknowledge the expected build time and suggest caching strategies.
5. Resource constraints need concrete analysis
The ADR notes "7GB RAM, 2 vCPU may constrain Claude Code" under consequences but doesn't analyze whether this is actually viable. The gateway runs Flask + Squid proxy, the sandbox runs Claude Code (Node.js) — what's the expected memory footprint? If it won't fit in 7GB, the ADR should say so and propose alternatives (larger runners, dropping Squid in GHA mode).
6. $GITHUB_WORKSPACE path mapping needs detail
The gateway's worktree manager creates worktrees at ~/.egg-worktrees/{container_id}/{repo_name} from the source repo's .git. In GHA, the .git is at $GITHUB_WORKSPACE/.git. The ADR should be explicit about how the workspace path maps through the gateway's worktree creation — specifically, the gateway needs the .git directory mounted at a path it knows about.
Minor
- Ensure
172.32.0.0/24doesn't collide with the runner's own Docker networks. - Open Question 2 (GHCR vs Docker Hub): GHCR is the obvious choice given the GitHub-native context — doesn't feel like a real open question.
- No mention of what happens if the GHA runner is killed mid-run (orphaned containers/networks).
What's good
- Correct decision to keep the full gateway stack for credential isolation.
- Shell entrypoint over docker-compose is the right call for Phase 1.
- Alternatives considered section is thorough with well-reasoned rejections.
- Phased approach with clear deliverables and success criteria.
Recommendation
Address #1 (API flow accuracy), #2 (config completeness), and #3 (API key routing) before accepting — these would cause implementation friction. #4 (build time) is worth acknowledging explicitly even if deferred to Phase 2.
— Authored by egg
There was a problem hiding this comment.
Addressing all review feedback:
@jwbron inline comments:
Re: OAuth token (line 69): Agreed. Changed anthropic-api-key to anthropic-oauth-token. The token is passed to the gateway as CLAUDE_CODE_OAUTH_TOKEN, matching the gateway's credential priority (OAuth > API key). The sandbox never sees it — all API calls route through the gateway's /v1/messages proxy.
Re: Default mode (line 71): Agreed. Changed default to auto, which queries GitHub API for repo visibility. Private/internal repos → private mode, public repos → public mode.
Re: Default model (line 73): Agreed. Changed to opus.
Re: Bot account (line 64): Agreed. Added bot-github-token and bot-username inputs. When bot-github-token is provided, it's passed to the gateway as BOT_GITHUB_TOKEN. The generated repositories.yaml now includes bot_username, repo_settings with auth_mode, and user_mode — matching the full config format expected by repo_parser.py.
Re: Open question 1 (line 224): Resolved — referenced #82 for trigger templates in Phase 3.
Re: Open question 2 (line 225): Resolved — GHCR.
Re: Open question 3 (line 226): Resolved — supports both new branches and current branch. Gateway lockdowns apply as-is.
Re: Open question 4 (line 227): Resolved — deferred.
@james-in-a-box review issues:
#1 (API flow accuracy): Fixed. Steps 6-7 replaced with a single step reflecting the actual POST /api/v1/sessions/create atomic flow — pre-allocate container IP, then one API call that queries visibility, filters repos, creates worktrees, and registers the session.
#2 (Config completeness): Fixed. Generated repositories.yaml now includes writable_repos, bot_username, repo_settings with auth_mode, user_mode block, and local_repos.paths. Added explicit workspace path mapping detail.
#3 (API key routing): Fixed (now OAuth token routing). Clarified that the token goes to the gateway as CLAUDE_CODE_OAUTH_TOKEN, the sandbox sets ANTHROPIC_BASE_URL=http://egg-gateway:9848, and the gateway's /v1/messages proxy injects credentials. Added a dedicated "Anthropic credentials" subsection under Gateway Token Handling.
#4 (Build time): Agreed — moved GHCR images to Phase 1. Building from source is impractical (5-15 min build times). Phase 1 now includes the release-images.yml workflow as a deliverable.
#5 (Resource constraints): Added a concrete Resource Analysis section with estimated memory footprint table (~850 MB - 1.15 GB baseline, leaving ~5.5-6 GB for Claude Code). Noted Squid could be dropped if tight, and larger runners as a recommendation.
#6 (Workspace path mapping): Added explicit detail — $GITHUB_WORKSPACE/.git bind-mounted into gateway at /repos/{repo-name}/.git, worktrees created at ~/.egg-worktrees/{container_id}/{repo_name}, path returned by session API and mounted into sandbox.
Minor items:
- Network collision: Changed to dynamically allocated subnet (inspects existing Docker networks).
- GHCR: Resolved per owner feedback.
- Orphaned containers: Added
trap EXIThandler note and clarified that hard-killed runner VMs are recycled by GHA.
— Authored by egg
Detailed technical plan for Phase 1 implementation of the GitHub Actions ADR (#98). Covers all deliverables (action.yml, entrypoint.sh, config generation, GHCR image publishing, integration tests), maps each step to existing codebase references, and identifies risks and open items. Closes #78 (partially — plan only, implementation to follow)
Keep GitHub Actions Support entry, drop removed Egg Repository Onboarding entry that no longer exists on main.
Detailed technical plan for Phase 1 implementation of the GitHub Actions ADR (#98). Covers all deliverables (action.yml, entrypoint.sh, config generation, GHCR image publishing, integration tests), maps each step to existing codebase references, and identifies risks and open items. Closes #78 (partially — plan only, implementation to follow)
* Add implementation plan for GitHub Actions support Detailed technical plan for Phase 1 implementation of the GitHub Actions ADR (#98). Covers all deliverables (action.yml, entrypoint.sh, config generation, GHCR image publishing, integration tests), maps each step to existing codebase references, and identifies risks and open items. Closes #78 (partially — plan only, implementation to follow) * Address review feedback on GHA implementation plan Correct repo_parser.py attribution to config/repo_config.py and shared/egg_config/config.py, add ADR dependency caveat, document .git shadow mount rationale, clarify dynamic subnet allocation for GHA, scope .dockerignore to separate PR, improve timeout mechanism to use docker stop, use github.event.repository.visibility context variable for mode detection, and pin image tags in action.yml. * Add ADR for GitHub Actions support (#98) * Add ADR for GitHub Actions support (#78) * Address PR #98 review feedback on GHA ADR --------- Co-authored-by: egg <egg@example.com> * Add implementation plan for GitHub Actions support Detailed technical plan for Phase 1 implementation of the GitHub Actions ADR (#98). Covers all deliverables (action.yml, entrypoint.sh, config generation, GHCR image publishing, integration tests), maps each step to existing codebase references, and identifies risks and open items. Closes #78 (partially — plan only, implementation to follow) * Address review feedback on GHA implementation plan Correct repo_parser.py attribution to config/repo_config.py and shared/egg_config/config.py, add ADR dependency caveat, document .git shadow mount rationale, clarify dynamic subnet allocation for GHA, scope .dockerignore to separate PR, improve timeout mechanism to use docker stop, use github.event.repository.visibility context variable for mode detection, and pin image tags in action.yml. * Implement GitHub Actions support (Phase 1 MVP) Add composite GitHub Action that orchestrates the full egg stack (gateway + sandbox) within a GHA runner. This enables running egg in CI/CD pipelines while maintaining the same security model as local execution. Deliverables: - action/action.yml: Composite action definition with inputs/outputs - action/entrypoint.sh: Container orchestration (pull, network, gateway, session, sandbox lifecycle with cleanup trap) - action/generate-config.sh: Ephemeral config generation for gateway - .github/workflows/release-images.yml: GHCR image publishing on release - .github/workflows/test-action.yml: Integration tests for the action - gateway/Dockerfile: Fix EXPOSE ports (9847->9848, 3128->3129) Issue: #78 * Address review feedback on Phase 1 implementation - Fix proxy var leak in exec mode: don't pass HTTP_PROXY/HTTPS_PROXY to sandbox container since run_exec() doesn't strip them before exec'ing Claude Code. Network isolation maintained via DNS and network topology. - Remove session response echo that leaked full session token to CI logs. The redacted token (first 8 chars) is still printed. - Replace bc-based health check timing with bash SECONDS builtin for portability across self-hosted runners. - Add Squid proxy health check for private mode — verifies proxy is accepting connections before starting sandbox. - Remove redundant GITHUB_USER_TOKEN from secrets.env — gateway reads it from the environment variable, not from this file. - Add EGG_QUIET=1 to sandbox container to suppress startup banner noise in CI logs. - Use associative array in allocate_subnet for O(1) subnet lookups instead of repeated grep. - Update test-action.yml assertion for secrets.env contents. * Fix CI failures in test-action workflow - Use $GITHUB_RUN_ID instead of hardcoded values (99999/88888) — GHA built-in env vars cannot be overridden by step-level env blocks - Replace `! grep` with if/then/exit pattern to avoid SC2251 (errexit skip under negated command) * Fix config generation test for GHA built-in env vars GITHUB_REPOSITORY, GITHUB_ACTOR, and GITHUB_ACTOR_ID are also built-in GHA variables that cannot be overridden by step-level env blocks. Validate against the actual runtime values instead of hardcoded test values. Clean up config dir between test steps since both now use the same GITHUB_RUN_ID. * Fix grep regex issue with bot actor names GITHUB_ACTOR can be "app[bot]" where [bot] is interpreted as a regex character class. Use grep -F for fixed string matching in all config generation test assertions. * Move GHA ADR from not-implemented to in-progress Phase 1 implementation is underway in PR #111. Update ADR status from "Proposed" to "In Progress", move the file to docs/adr/in-progress/, and fix references in the ADR index and implementation plan. --------- Co-authored-by: egg <egg@example.com> Co-authored-by: james-in-a-box[bot] <246424927+james-in-a-box[bot]@users.noreply.github.com>
Add design proposal for running egg in GitHub Actions
This ADR proposes a composite GitHub Action that orchestrates the full
egg stack (gateway + sandbox) within a GHA runner, mounting the
actions/checkout'd repo as the working repository.The design preserves egg's security model (credential isolation via
gateway, policy enforcement, .git shadowing) while adapting to the
GHA environment. Users would reference the action with a prompt,
Anthropic API key, and GitHub token as inputs.
Key decisions:
Three implementation phases: MVP core action, optimization with
pre-built images, and advanced features (private mode, multi-repo,
trigger templates).
Closes #78
Test plan:
Authored-by: egg